package com.xbang.attendance.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import com.xbang.attendance.entity.product.Product;
import com.xbang.attendance.entity.stock.Inventory;
import com.xbang.attendance.entity.system.AddProductLog;
import com.xbang.attendance.entity.system.Warehouse;
import com.xbang.attendance.entity.system.WarehouseProductAgreement;
import com.xbang.attendance.security.support.SecurityUserHolder;
import com.xbang.attendance.service.InventoryService;
import com.xbang.attendance.service.ProductService;
import com.xbang.attendance.service.WarehouseService;
import com.xbang.attendance.utils.FieldUtil;
import com.xbang.core.utils.ReflectionUtils;

/**
 * @author huawei
 * @email alonelaval@gmail.com
 */
public class WarehouseProductAnalyzeImpl extends AbstractAnalyzeService {

	private WarehouseService warehouseService;
	private Map<String, String> fieldMapping = new HashMap<String, String>();

	private ProductService productService;
	private InventoryService inventoryService;

	private static final String REAL = "real";
	@Override
	public void analyse(File file,String type) throws Exception {

		//System.out.println(type);
		POIFSFileSystem fs = null;
		HSSFWorkbook wb = null;
		fs = new POIFSFileSystem(new FileInputStream(file));
		wb = new HSSFWorkbook(fs);

		for (int i = 0; i < wb.getNumberOfSheets(); i++) {
			
			HSSFSheet sheet = wb.getSheetAt(i);
			
			setupExcelFieldMappings(sheet);
	
			int proColumnIndex = getProIndex();
			int wareColumnIndx = getWareIndex();
			for (Row row : sheet) {
					if (row.getRowNum() == 0) {
						continue;
					}
					if (getCellValue(row.getCell(0)) == null || getCellValue(row.getCell(0)).toString().trim().isEmpty()) {
						continue;
					}
					Cell proData = row.getCell(proColumnIndex);
					Cell wareData = row.getCell(wareColumnIndx);
					Product product = productService.getProductByCode(ReflectionUtils.parseString(getCellValue(proData)));
					Warehouse warehouse = warehouseService.getWarehouseByCode(ReflectionUtils.parseString(getCellValue(wareData)));
		
					if (product == null) {
						throw new Exception("产品编码为：" + getCellValue(proData) + "不存在！");
					}
					if (warehouse == null) {
						throw new Exception("仓储编码为：" + getCellValue(wareData) + "不存在！");
					}
					Cell number = row.getCell(getNumberIndex(type));
					//System.out.println(warehouse.getCode()+"   "+product.getProductCode());
					
					//excute(warehouse, product, number);
					if(type.equals(REAL)){
						executeReal(warehouse, product, number);
					}else{
						executeVirtual(warehouse, product, number);
					}	
				}
		}
	}
	
	@Override
	public String analyse(File file,String webPath,Object ... object) throws Exception {

		//System.out.println(type);
		POIFSFileSystem fs = null;
		HSSFWorkbook wb = null;
		fs = new POIFSFileSystem(new FileInputStream(file));
		wb = new HSSFWorkbook(fs);
		
		String genericExcelFile = "compare.xls";
		File fi = new File(webPath + "//" + genericExcelFile);
		//Map<Integer,List> map = getRegionAndWarehouse();
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet2 = workbook.createSheet("compare");
		int rIndex = 0;
		HSSFRow row2= sheet2.createRow(rIndex++);
		int c = 0;
		for (FieldUtil.Filed field : FieldUtil.getCompareFields()) {
			HSSFCell cell = row2.createCell(c);
			cell.setCellValue(field.getName());
			c++;
		}
		
		for (int i = 0; i < wb.getNumberOfSheets(); i++) {
			
			HSSFSheet sheet = wb.getSheetAt(i);
			
			setupExcelFieldMappings(sheet);
	
			int proColumnIndex = getProIndex();
			int wareColumnIndx = getWareIndex();
			for (Row row : sheet) {
					if (row.getRowNum() == 0) {
						continue;
					}
					if (getCellValue(row.getCell(0)) == null || getCellValue(row.getCell(0)).toString().trim().isEmpty()) {
						continue;
					}
					Cell proData = row.getCell(proColumnIndex);
					Cell wareData = row.getCell(wareColumnIndx);
					Product product = productService.getProductByCode(ReflectionUtils.parseString(getCellValue(proData)));
					Warehouse warehouse = warehouseService.getWarehouseByCode(ReflectionUtils.parseString(getCellValue(wareData)));
		
					if (product == null) {
						throw new Exception("产品编码为：" + getCellValue(proData) + "不存在！");
					}
					if (warehouse == null) {
						throw new Exception("仓储编码为：" + getCellValue(wareData) + "不存在！");
					}
					Cell number = row.getCell(getNumberIndex(REAL));
					WarehouseProductAgreement agreement = warehouseService.getWarehouseProductAgreement(warehouse, product);
					if(agreement == null){
						throw new Exception("仓储编码：" + getCellValue(wareData) + " 的产品："+getCellValue(proData)+"的约定不存在，请先导入约定！");
					}
					WarehouseProductAgreement agreement2 = new WarehouseProductAgreement();
					String propertyName = fieldMapping.get("配件数量").split(":")[0];
					//System.out.println(getCellValue(number));
					ReflectionUtils.setFeildByApacheCheckString(agreement2, propertyName, ReflectionUtils.parseString(getCellValue(number)));
					if(agreement.getNumber().doubleValue() != agreement2.getNumber().doubleValue()){
						HSSFRow row3= sheet2.createRow(rIndex++);
						c = 0;
						HSSFCell c1 = row3.createCell(c++);
						c1.setCellValue(warehouse.getCode());
						HSSFCell c2 = row3.createCell(c++);
						c2.setCellValue(warehouse.getName());
						HSSFCell c3 = row3.createCell(c++);
						c3.setCellValue(product.getProductCode());
						HSSFCell c4 = row3.createCell(c++);
						c4.setCellValue(product.getProductName());
						HSSFCell c5 = row3.createCell(c++);
						c5.setCellValue(agreement.getNumber().doubleValue());
						HSSFCell c6 = row3.createCell(c++);
						c6.setCellValue(agreement2.getNumber().doubleValue());
						HSSFCell c7= row3.createCell(c++);
						c7.setCellValue(agreement.getNumber().subtract(agreement2.getNumber()).doubleValue());
					}
				}
		}
		sheet2.autoSizeColumn(( short ) 0 ); // 调整第一列宽度 
		sheet2.autoSizeColumn(( short ) 1 ); // 调整第二列宽度 
		sheet2.autoSizeColumn(( short ) 2 ); // 调整第一列宽度 
		sheet2.autoSizeColumn(( short ) 3 ); // 调整第二列宽度 
		sheet2.autoSizeColumn(( short ) 4 ); // 调整第一列宽度 
		sheet2.autoSizeColumn(( short ) 5 ); // 调整第二列宽度 
		sheet2.autoSizeColumn(( short ) 6 ); // 调整第一列宽度 
		sheet2.autoSizeColumn(( short ) 7 ); // 调整第二列宽度 
		
		OutputStream os = new FileOutputStream(fi);
		workbook.write(os);// 写入
		InputStream in = new FileInputStream(fi);
		os.close();
		in.close();
		return genericExcelFile;
	}
	
	/**
	 	执行导入，导入真实的约定，库存等于真实减虚拟
	 */
	private void executeReal(Warehouse warehouse,Product product,Cell number)throws Exception{
		WarehouseProductAgreement agreement = warehouseService.getWarehouseProductAgreement(warehouse, product);
		if (agreement == null) { //没有约定的情况
			
			agreement = new WarehouseProductAgreement();
			agreement.setProduct(product);
			agreement.setWarehouse(warehouse);
			String propertyName = fieldMapping.get("配件数量").split(":")[0];
			ReflectionUtils.setFeildByApacheCheckString(agreement, propertyName, ReflectionUtils.parseString(getCellValue(number)));
			
			//AddProductLog.
			Inventory inventory = inventoryService.getInventoryByParameters(warehouse, product);
			
			if(inventory == null)
			{
				inventory = new Inventory();
				inventory.initial(warehouse, product);
			}
			inventory.setAgreementAmount(agreement.getNumber());
			inventory.setAmount(agreement.getNumber());
			
			if(agreement.getNumber().doubleValue() < 0){ //如果小于0的话，忽略它
				return;
			}
			inventory.updateOperation(SecurityUserHolder.getCurrentUser().getUsername());
			agreement.setLastModifyDate(new Date());
			
			
			AddProductLog addProductLog = new AddProductLog();
			addProductLog.initial(warehouse, product, agreement.getNumber(), false);
			
			/*设置虚拟*/
			inventory.setVirtualAmount(new BigDecimal(0));
			inventory.setOutAmount(new BigDecimal(0));
			inventory.setRealAmount(agreement.getNumber());
			addProductLog.setVirtual(false);
			agreement.setVirtualNumber(new BigDecimal(0));
			
			
			
			inventoryService.save(addProductLog);
			warehouseService.save(agreement);
			inventoryService.save(inventory);
			
		} else { //有约定的情况，并且假设已经有发送的，并且还有虚拟的
			
			Inventory inventory = inventoryService.getInventoryByParameters(warehouse, product);
			
			String propertyName = fieldMapping.get("配件数量").split(":")[0];
					
			
			WarehouseProductAgreement tempAgreement = new WarehouseProductAgreement();
			
			ReflectionUtils.setFeildByApacheCheckString(tempAgreement, propertyName, ReflectionUtils.parseString(getCellValue(number)));
			
			
			if(agreement.getNumber().add(tempAgreement.getNumber()).doubleValue() <0){
				throw new Exception("仓储编码为：" + warehouse.getCode() + " 的 产品编码: "+product.getProductCode()+" 的约定数量不能为负数!");
			}
			if(agreement.getNumber().add(tempAgreement.getNumber()).doubleValue() < agreement.getVirtualNumber().doubleValue()){
				throw new Exception("仓储编码为：" + warehouse.getCode() + " 的 产品编码: "+product.getProductCode()+" 的约定数量不能小于虚拟数量!");
			}
			agreement.setNumber(agreement.getNumber().add(tempAgreement.getNumber()));
			
			agreement.setLastModifyDate(new Date());
			
			inventory.setAmount(inventory.getAmount().add(tempAgreement.getNumber()));
			
			inventory.setRealAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()));
			
			inventory.setAgreementAmount(agreement.getNumber());
			
			
//			if(tempAgreement.getNumber().doubleValue() >= 0){ //加约定的情况
//				
//				
//			}
//			else{
//				//当前约定-减去的约定-虚拟约定 -原始库存
////				if(agreement.getNumber().add(tempAgreement.getNumber())
////						.subtract(agreement.getVirtualNumber())
////					.subtract(inventory.getOutAmount()).doubleValue() < 0){
////					throw new Exception("仓储编码为：" + warehouse.getCode() + " 的 产品编码: "+product.getProductCode()+" 的约定库存不足，导入失败！");
////				}
//				
//				
//			}
			
			inventory.updateOperation(SecurityUserHolder.getCurrentUser().getUsername());
	
			
			AddProductLog addProductLog = new AddProductLog();
			addProductLog.initial(warehouse, product, tempAgreement.getNumber(), false);
			
			inventoryService.save(addProductLog);
			warehouseService.update(agreement);
			inventoryService.update(inventory);
		}			
	}
	/**
	 	执行导入，导入虚拟的约定，库存等于真实减虚拟
	 */
	private void executeVirtual(Warehouse warehouse,Product product,Cell number)throws Exception{
		
		WarehouseProductAgreement agreement = warehouseService.getWarehouseProductAgreement(warehouse, product);
		if(agreement == null){
			throw new Exception("仓储编码为：" + warehouse.getCode() + " 的 产品编码: "+product.getProductCode()+" 不存在，请先导入约定数量，再导入虚拟数量！");
		}
		Inventory inventory = inventoryService.getInventoryByParameters(warehouse, product);
		
		String propertyName = "virtualNumber";
				
		
		WarehouseProductAgreement tempAgreement = new WarehouseProductAgreement();
		
		ReflectionUtils.setFeildByApacheCheckString(tempAgreement, propertyName, ReflectionUtils.parseString(getCellValue(number)));
		
		
		if(agreement.getNumber().doubleValue() > 0){ //有约定
			//虚拟大于0，并且没有虚拟库存
			if( tempAgreement.getVirtualNumber().doubleValue() > 0 && agreement.getVirtualNumber().doubleValue() == 0){
				 //真实必须大于虚拟
				if(agreement.getNumber().doubleValue() >= tempAgreement.getVirtualNumber().doubleValue())
				{	
					
					agreement.setVirtualNumber(tempAgreement.getVirtualNumber());
					//约定减虚拟减已经出库 =
					inventory.setAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()).subtract(inventory.getOutAmount()));
					//虚拟
					inventory.setVirtualAmount(agreement.getVirtualNumber());
					// 库存
					inventory.setRealAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()));
				}
			}
			//虚拟大于0，有虚拟库存
			if( tempAgreement.getVirtualNumber().doubleValue() > 0 && agreement.getVirtualNumber().doubleValue() > 0){
				agreement.setVirtualNumber(tempAgreement.getVirtualNumber().add(agreement.getVirtualNumber()));
				//System.out.println();
				 //真实必须大于等于虚拟
				if(agreement.getNumber().doubleValue() >= agreement.getVirtualNumber().doubleValue())
				{	
					//agreement.setVirtualNumber(tempAgreement.getVirtualNumber());
					//约定减虚拟减已经出库 =
					inventory.setAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()).subtract(inventory.getOutAmount()));
					//虚拟
					inventory.setVirtualAmount(agreement.getVirtualNumber());
					// 库存
					inventory.setRealAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()));
				}
			}
			//虚拟小于0，有虚拟库存
			if( tempAgreement.getVirtualNumber().doubleValue() < 0 && agreement.getVirtualNumber().doubleValue() > 0){
				agreement.setVirtualNumber(tempAgreement.getVirtualNumber().add(agreement.getVirtualNumber()));
				 //虚拟库存必须大于等于0
				if(agreement.getVirtualNumber().doubleValue() >= 0)
				{	
					//agreement.setVirtualNumber(tempAgreement.getVirtualNumber());
					//约定减虚拟减已经出库 =
					inventory.setAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()).subtract(inventory.getOutAmount()));
					//虚拟
					inventory.setVirtualAmount(agreement.getVirtualNumber());
					// 库存
					inventory.setRealAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()));
				}
			}
		}
		
//		agreement.setNumber(agreement.getNumber().add(tempAgreement.getNumber()));
//		
//		agreement.setLastModifyDate(new Date());
//		
//		inventory.setAmount(inventory.getAmount().add(tempAgreement.getNumber()));
//		
//		inventory.setRealAmount(agreement.getNumber().subtract(agreement.getVirtualNumber()));
//		
//		inventory.setAgreementAmount(agreement.getNumber());
//		
		
//		if(tempAgreement.getNumber().doubleValue() >= 0){ //加约定的情况
//			
//			
//		}
//		else{
//			//当前约定-减去的约定-虚拟约定 -原始库存
////			if(agreement.getNumber().add(tempAgreement.getNumber())
////					.subtract(agreement.getVirtualNumber())
////				.subtract(inventory.getOutAmount()).doubleValue() < 0){
////				throw new Exception("仓储编码为：" + warehouse.getCode() + " 的 产品编码: "+product.getProductCode()+" 的约定库存不足，导入失败！");
////			}
//			
//			
//		}
		
		inventory.updateOperation(SecurityUserHolder.getCurrentUser().getUsername());

		AddProductLog addProductLog = new AddProductLog();
		addProductLog.initial(warehouse, product, tempAgreement.getVirtualNumber(), true);
		
		agreement.setLastModifyVirtualDate(new Date());
		inventoryService.save(addProductLog);
		warehouseService.update(agreement);
		inventoryService.update(inventory);
	}
	
	
	/**
	 * 
	 * 原始的做法
	 */
	private void execute(Warehouse warehouse,Product product,Cell number)throws Exception{
		WarehouseProductAgreement agreement = warehouseService.getWarehouseProductAgreement(warehouse, product);
		if (agreement == null) {
			
			agreement = new WarehouseProductAgreement();
			agreement.setProduct(product);
			agreement.setWarehouse(warehouse);
			String propertyName = fieldMapping.get("配件数量").split(":")[0];
			ReflectionUtils.setFeildByApacheCheckString(agreement, propertyName, ReflectionUtils.parseString(getCellValue(number)));
			
			//AddProductLog.
			Inventory inventory = inventoryService.getInventoryByParameters(warehouse, product);
			
			if(inventory == null)
			{
				inventory = new Inventory();
				inventory.initial(warehouse, product);
			}
			inventory.setAgreementAmount(agreement.getNumber());
			inventory.setAmount(agreement.getNumber());
			
			if(agreement.getNumber().doubleValue() < 0){ //如果小于0的话，忽略它
				return;
			}
			inventory.updateOperation(SecurityUserHolder.getCurrentUser().getUsername());
			agreement.setLastModifyDate(new Date());
			
			AddProductLog addProductLog = new AddProductLog();
			addProductLog.initial(warehouse, product, agreement.getNumber(), false);
			
			inventoryService.save(addProductLog);
			warehouseService.save(agreement);
			inventoryService.save(inventory);
			
		} else {
			
			Inventory inventory = inventoryService.getInventoryByParameters(warehouse, product);
			
			String propertyName = fieldMapping.get("配件数量").split(":")[0];
					
			
			WarehouseProductAgreement tempAgreement = new WarehouseProductAgreement();
			
			ReflectionUtils.setFeildByApacheCheckString(tempAgreement, propertyName, ReflectionUtils.parseString(getCellValue(number)));
			
			
			

			agreement.setNumber(agreement.getNumber().add(tempAgreement.getNumber()));	
			agreement.setLastModifyDate(new Date());
			inventory.setAmount(inventory.getAmount().add(tempAgreement.getNumber()));
			
			inventory.setAgreementAmount(agreement.getNumber());
			
			inventory.updateOperation(SecurityUserHolder.getCurrentUser().getUsername());
	
			
			AddProductLog addProductLog = new AddProductLog();
			addProductLog.initial(warehouse, product, tempAgreement.getNumber(), false);
			
			inventoryService.save(addProductLog);
			warehouseService.update(agreement);
			inventoryService.update(inventory);
		}			
	}
	
	
	
	
	private int getProIndex() {
		return excelFieldMapping.get("配件代码");

	}

	private int getWareIndex() {
		return excelFieldMapping.get("仓储编码");
	}

	private int getNumberIndex(String type) {
		if(type.equals(REAL))
			return excelFieldMapping.get("配件数量");
		else {
			return excelFieldMapping.get("虚拟数量");
		}
	}

	public WarehouseService getWarehouseService() {
		return warehouseService;
	}

	public void setWarehouseService(WarehouseService warehouseService) {
		this.warehouseService = warehouseService;
	}

	public ProductService getProductService() {
		return productService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public Map<String, String> getFieldMapping() {
		return fieldMapping;
	}

	public void setFieldMapping(Map<String, String> fieldMapping) {
		this.fieldMapping = fieldMapping;
	}

	public InventoryService getInventoryService() {
		return inventoryService;
	}

	public void setInventoryService(InventoryService inventoryService) {
		this.inventoryService = inventoryService;
	}

}
